package com.gopay.common.rcs.manager.translimit.impl;

import java.math.BigDecimal;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.gopay.common.constants.rcs.TranDirection;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.domain.acps.AcctProd;
import com.gopay.common.domain.rcs.RcsBAcctLimitStatistics;
import com.gopay.common.domain.rcs.req.RcsTransLimitRequest.RequestType;
import com.gopay.common.rcs.dao.translimit.RcsBAcctLimitStatisticsDAO;
import com.gopay.common.rcs.manager.translimit.RcsBAcctLimitStatisticsManager;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.NumberUtils;

/**
 * 额度管理manager层
 * 
 * @RcsGAcctLimitStatisticsManagerImpl.java
 * @author liujy
 * @2013-7-23 下午6:34:46 www.gopay.com.cn Inc.All rights reserved.
 */
@Service("rcsBAcctLimitStatisticsManager")
public class RcsBAcctLimitStatisticsManagerImpl implements RcsBAcctLimitStatisticsManager {
  
    @Resource(name = "rcsBAcctLimitStatistics")
    private RcsBAcctLimitStatisticsDAO dao;
    private Object lock = new Object();

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class, RuntimeException.class })
    public RcsBAcctLimitStatistics getTransLimitStatistics(String custId, AcctProd acctProd,
            IntTxnCd intTxnCd, TranDirection tranDirection, String tranDate, String pbocBankCode,
            String bankAcctNum, String bankName, String bankAcctName) {
        return getOrAddTransLimitStatistics(custId, acctProd, intTxnCd, tranDirection, tranDate, pbocBankCode,
                bankAcctNum, bankName, bankAcctName);

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class, RuntimeException.class })
    public RcsBAcctLimitStatistics saveOrUpdateTransLimitStatistics(String custId, AcctProd acctProd,
            IntTxnCd intTxnCd, TranDirection tranDirection, String tranDate, BigDecimal tranAmt, String pbocBankCode,
            String bankAcctNum, String bankName, String bankAcctName, RequestType updateType) {
        RcsBAcctLimitStatistics statistics = getOrAddTransLimitStatistics(custId, acctProd, intTxnCd, tranDirection, tranDate, pbocBankCode,
                bankAcctNum, bankName, bankAcctName);
        if (RequestType.add.equals(updateType)) {
            addTranLimit(statistics, intTxnCd, tranAmt);
        }else if(RequestType.subtract_not_times_limit.equals(updateType)
        		|| RequestType.subtract.equals(updateType)){
        	subtractTranLimit(statistics, intTxnCd, tranAmt, updateType);
        }
        dao.update(statistics);
        return statistics;
    }

    /**
     * 
     * @param statistics
     * @param intTxnCd
     * @param tranAmt
     */
    private void addTranLimit(RcsBAcctLimitStatistics statistics, IntTxnCd intTxnCd, BigDecimal tranAmt) {
        statistics.setDayLimitStatcs(statistics.getDayLimitStatcs().add(tranAmt));
        statistics.setDayTimesStatcs(statistics.getDayTimesStatcs() + 1);
        statistics.setLastUpdTrancode(intTxnCd.value);
        statistics.setLastUpdTs(DateUtils.getSystemDate());
    }

    /**
     * 
     * @param statistics
     * @param intTxnCd
     * @param tranAmt
     */
    private void subtractTranLimit(RcsBAcctLimitStatistics statistics, IntTxnCd intTxnCd, BigDecimal tranAmt, RequestType updateType) {
        BigDecimal dayLimitStatcs = statistics.getDayLimitStatcs().compareTo(tranAmt) == 1 ? statistics
                .getDayLimitStatcs().subtract(tranAmt) : NumberUtils.getZero();
        statistics.setDayLimitStatcs(dayLimitStatcs);
        if(RequestType.subtract.equals(updateType)){
        	int dayTimesStatcs = statistics.getDayTimesStatcs() > 0 ? statistics.getDayTimesStatcs() - 1 : 0;
        	statistics.setDayTimesStatcs(dayTimesStatcs);
        }
        statistics.setLastUpdTrancode(intTxnCd.value);
        statistics.setLastUpdTs(DateUtils.getSystemDate());
    }

    /**
     * 
     * @param custId
     * @param acctProd
     * @param intTxnCd
     * @param tranDirection
     * @param tranDate
     * @return
     */
    private RcsBAcctLimitStatistics getOrAddTransLimitStatistics(String custId, AcctProd acctProd, IntTxnCd intTxnCd,
            TranDirection tranDirection, String tranDate, String pbocBankCode, String bankAcctNum,
            String bankName, String bankAcctName) {
        RcsBAcctLimitStatistics statistics = dao.findTransLimitStatistics(custId, acctProd, intTxnCd, tranDirection,
                pbocBankCode, bankAcctNum, tranDate);
        if (null == statistics) {
            synchronized (lock) {
                statistics = dao.findTransLimitStatistics(custId, acctProd, intTxnCd, tranDirection, pbocBankCode,
                        bankAcctNum, tranDate);
                if (null == statistics) {
                    statistics = new RcsBAcctLimitStatistics();
                    statistics.setCustId(custId);
                    statistics.setGopayIntTxnCd(intTxnCd.value);
                    statistics.setProdCode(acctProd.toString());
                    statistics.setTranDirection(tranDirection.value);
                    statistics.setStatcsDate(tranDate);
                    statistics.setPbocBankCode(pbocBankCode);
                    statistics.setBankAcctNum(bankAcctNum);
                    statistics.setBankName(bankName);
                    statistics.setBankAcctName(bankAcctName);
                    statistics.setDayLimitStatcs(new BigDecimal("0.00"));
                    statistics.setDayTimesStatcs(0);
                    statistics = dao.add(statistics);
                }
            }
        }
        return statistics;
    }
}
